package com.neusoft.databus.core.loadbalance;

import java.util.Map;

import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
import org.springframework.util.ConcurrentReferenceHashMap;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;

/**
 * description
 *
 * @author sunchf
 * @date 2019年2月20日 上午9:36:16
 */
public class StatefulCachingSpringLoadBalancerFactory extends CachingSpringLoadBalancerFactory {

    private volatile Map<String, FeignLoadBalancer> myCache = new ConcurrentReferenceHashMap<>();

    public StatefulCachingSpringLoadBalancerFactory(SpringClientFactory factory) {
        super(factory);
    }

    public StatefulCachingSpringLoadBalancerFactory(SpringClientFactory factory,
            LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {
        super(factory, loadBalancedRetryPolicyFactory);
    }

    @Override
    public FeignLoadBalancer create(String clientName) {
        FeignLoadBalancer client = this.myCache.get(clientName);
        if (client != null) {
            return client;
        }
        final IClientConfig config = this.factory.getClientConfig(clientName);
        final ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
        final ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
        client = this.loadBalancedRetryFactory != null
                ? new StatefulRetryableFeignLoadBalancer(lb, config, serverIntrospector, this.loadBalancedRetryFactory)
                : new FeignLoadBalancer(lb, config, serverIntrospector);
        this.myCache.put(clientName, client);
        return client;
    }

}
